package cn.lili.modules.lucene;

import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
import cn.lili.modules.search.entity.dto.ParamOptions;
import cn.lili.modules.search.entity.dto.SelectorOptions;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * @Author Sylow
 * @Description
 * @Date: Created in 14:35 2025/7/15
 */
@Service
public class GoodsAggregationService {

    public EsGoodsRelatedInfo aggregateGoodsRelatedInfo(IndexSearcher searcher, Query query) throws Exception {
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
        EsGoodsRelatedInfo result = new EsGoodsRelatedInfo();

        // 1. 聚合品牌（需要ID和URL）
        result.setBrands(aggregateBrands(searcher, topDocs));

        // 2. 聚合分类（需要名称）
        result.setCategories(aggregateCategories(searcher, topDocs));

        // 3. 聚合参数
        result.setParamOptions(aggregateAttributes(searcher, topDocs));

        return result;
    }

    private List<SelectorOptions> aggregateBrands(IndexSearcher searcher, TopDocs topDocs) throws IOException {
        // 使用Map存储品牌ID到品牌对象的映射
        Map<String, SelectorOptions> brandMap = new HashMap<>();
        IndexReader reader = searcher.getIndexReader();

        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = reader.document(scoreDoc.doc);

            // 获取品牌ID
            IndexableField brandIdField = doc.getField("brandId");
            if (brandIdField == null) continue;
            String brandId = brandIdField.stringValue();

            // 获取品牌名称
            String brandName = "";
            IndexableField brandNameField = doc.getField("brandName");
            if (brandNameField != null) {
                brandName = brandNameField.stringValue();
            }

            // 获取品牌URL
            String brandUrl = "";
            IndexableField brandUrlField = doc.getField("brandUrl");
            if (brandUrlField != null) {
                brandUrl = brandUrlField.stringValue();
            }

            if (brandId == null || brandId.isEmpty() || brandName == null || brandName.isEmpty()) {
                continue; // 跳过无效的品牌数据
            }

            // 如果尚未记录该品牌，则创建新条目
            if (!brandMap.containsKey(brandId)) {
                SelectorOptions option = new SelectorOptions();
                option.setName(brandName);
                option.setValue(brandId);
                option.setUrl(brandUrl);
                brandMap.put(brandId, option);
            }
        }

        return new ArrayList<>(brandMap.values());
    }

    private List<SelectorOptions> aggregateCategories(IndexSearcher searcher, TopDocs topDocs) throws IOException {
        // 使用Map存储分类ID到分类名称的映射
        Map<String, String> categoryNameMap = new HashMap<>();
        IndexReader reader = searcher.getIndexReader();

        // 第一轮：收集所有分类ID对应的名称
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = reader.document(scoreDoc.doc);

            // 获取分类路径字段
            IndexableField categoryPathField = doc.getField("categoryPath");
            if (categoryPathField == null) continue;
            String[] categoryIds = categoryPathField.stringValue().split(",");

            // 获取分类名称路径
            IndexableField categoryNamePathField = doc.getField("categoryNamePath");
            if (categoryNamePathField == null) continue;
            String[] categoryNames = categoryNamePathField.stringValue().split(",");

            // 确保ID和名称数组长度相同
            if (categoryIds.length != categoryNames.length) continue;

            // 填充映射关系
            for (int i = 0; i < categoryIds.length; i++) {
                categoryNameMap.put(categoryIds[i], categoryNames[i]);
            }
        }

        // 第二轮：实际聚合分类（按ID分组计数）
        Map<String, Integer> categoryCountMap = new HashMap<>();
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = reader.document(scoreDoc.doc);
            IndexableField categoryPathField = doc.getField("categoryPath");
            if (categoryPathField == null) continue;

            for (String categoryId : categoryPathField.stringValue().split(",")) {
                categoryCountMap.put(categoryId, categoryCountMap.getOrDefault(categoryId, 0) + 1);
            }
        }

        // 构建最终结果
        List<SelectorOptions> options = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : categoryCountMap.entrySet()) {
            String categoryId = entry.getKey();
            SelectorOptions option = new SelectorOptions();
            if (categoryNameMap.get(categoryId) == null || categoryNameMap.get(categoryId).isEmpty()) {
                // 如果没有找到对应的名称不添加
                continue;
            }
            option.setName(categoryNameMap.get(categoryId));
            option.setValue(categoryId);
            options.add(option);
        }

        return options;
    }

    private List<ParamOptions> aggregateAttributes(IndexSearcher searcher, TopDocs topDocs) throws Exception {
        Map<String, Set<String>> attributeMap = new HashMap<>();
        IndexReader reader = searcher.getIndexReader();

        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = reader.document(scoreDoc.doc);
            IndexableField[] fields = doc.getFields("attrValueAgg");

            for (IndexableField field : fields) {
                String fullValue = field.stringValue();
                String[] parts = fullValue.split("::", 2);
                if (parts.length == 2) {
                    String paramName = parts[0];
                    String paramValue = parts[1];
                    attributeMap.computeIfAbsent(paramName, k -> new HashSet<>()).add(paramValue);
                }
            }
        }

        List<ParamOptions> params = new ArrayList<>();
        attributeMap.forEach((key, values) -> {
            ParamOptions param = new ParamOptions();
            param.setKey(key);
            param.setValues(new ArrayList<>(values));
            params.add(param);
        });

        return params;
    }
}
